home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / fs / open.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  13KB  |  407 lines

  1. /* This file contains the procedures for creating, opening, closing, and
  2.  * seeking on files.
  3.  *
  4.  * The entry points into this file are
  5.  *   do_creat:    perform the CREAT system call
  6.  *   do_mknod:    perform the MKNOD system call
  7.  *   do_open:    perform the OPEN system call
  8.  *   do_close:    perform the CLOSE system call
  9.  *   do_lseek:  perform the LSEEK system call
  10.  *   do_mkdir:    perform the MKDIR system call
  11.  */
  12.  
  13. #include "fs.h"
  14. #include <minix/callnr.h>
  15. #include <sys/stat.h>
  16. #include <fcntl.h>
  17. #include "buf.h"
  18. #include "file.h"
  19. #include "fproc.h"
  20. #include "inode.h"
  21. #include "param.h"
  22.  
  23. PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
  24. PRIVATE char dot1[NAME_MAX] = ".\0\0\0\0\0\0\0\0\0\0\0\0";
  25. PRIVATE char dot2[NAME_MAX] =  "..\0\0\0\0\0\0\0\0\0\0\0";
  26.  
  27. FORWARD int common_open();
  28. FORWARD struct inode *new_node();
  29. FORWARD int pipe_open();
  30.  
  31. /*===========================================================================*
  32.  *                do_creat                     *
  33.  *===========================================================================*/
  34. PUBLIC int do_creat()
  35. {
  36. /* Perform the creat(name, mode) system call. */
  37.   /* get name */
  38.   if (fetch_name(name, name_length, M3) != OK) return(err_code);
  39.   return common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) mode);
  40. }
  41.  
  42.  
  43. /*===========================================================================*
  44.  *                do_mknod                     *
  45.  *===========================================================================*/
  46. PUBLIC int do_mknod()
  47. {
  48. /* Perform the mknod(name, mode, addr) system call. */
  49.  
  50.   register mode_t bits;
  51.   unsigned int size;
  52.  
  53.   /* Only the super_user may make nodes other than fifos. */
  54.   if (!super_user && ((mode & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
  55.   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  56.   bits = (mode & I_TYPE) | (mode & ALL_MODES & fp->fp_umask);
  57.   size = (unsigned int) name2;
  58.   put_inode(new_node(user_path, bits, (zone_nr) addr), (off_t)size*BLOCK_SIZE);
  59.   return(err_code);
  60. }
  61.  
  62.  
  63. /*===========================================================================*
  64.  *                new_node                     *
  65.  *===========================================================================*/
  66. PRIVATE struct inode *new_node(path, bits, z0, lsize)
  67. char *path;            /* pointer to path name */
  68. mode_t bits;            /* mode of the new inode */
  69. zone_nr z0;            /* zone number 0 for new inode */
  70. off_t lsize;            /* size of the special file */
  71. {
  72. /* New_node() is called by common_open(), do_mknod(), and do_mkdir().  
  73.  * In all cases it allocates a new inode, makes a directory entry for it on 
  74.  * the path 'path', and initializes it.  It returns a pointer to the inode if 
  75.  * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code'
  76.  * to an appropriate value (OK or an error code).
  77.  */
  78.  
  79.   register struct inode *rlast_dir_ptr, *rip;
  80.   register int r;
  81.   char string[NAME_MAX];
  82.  
  83.   /* See if the path can be opened down to the last directory. */
  84.   if ((rlast_dir_ptr = last_dir(path, string)) == NIL_INODE) return(NIL_INODE);
  85.  
  86.   /* The final directory is accessible. Get final component of the path. */
  87.   rip = advance(rlast_dir_ptr, string);
  88.   if ( rip == NIL_INODE && err_code == ENOENT) {
  89.     /* Last path component does not exist.  Make new directory entry. */
  90.     if ( (rip = alloc_inode(rlast_dir_ptr->i_dev, bits)) == NIL_INODE) {
  91.         /* Can't creat new inode: out of inodes. */
  92.         put_inode(rlast_dir_ptr);
  93.         return(NIL_INODE);
  94.     }
  95.  
  96.     /* Force inode to the disk before making directory entry to make
  97.      * the system more robust in the face of a crash: an inode with
  98.      * no directory entry is much better than the opposite.
  99.      */
  100.     rip->i_nlinks++;
  101.     rip->i_zone[0] = z0;        /* major/minor device numbers */
  102.     rip->i_size = lsize;        /* size (needed for block specials) */
  103.     rw_inode(rip, WRITING);        /* force inode to disk now */
  104.  
  105.     /* New inode acquired.  Try to make directory entry. */
  106.     if ((r = search_dir(rlast_dir_ptr, string, &rip->i_num,ENTER)) != OK) {
  107.         put_inode(rlast_dir_ptr);
  108.         rip->i_nlinks--;    /* pity, have to free disk inode */
  109.         rip->i_dirt = DIRTY;    /* dirty inodes are written out */
  110.         put_inode(rip);    /* this call frees the inode */
  111.         err_code = r;
  112.         return(NIL_INODE);
  113.     }
  114.  
  115.   } else {
  116.     /* Either last component exists, or there is some problem. */
  117.     if (rip != NIL_INODE)
  118.         r = EEXIST;
  119.     else
  120.         r = err_code;
  121.   }
  122.  
  123.   /* Return the directory inode and exit. */
  124.   put_inode(rlast_dir_ptr);
  125.   err_code = r;
  126.   return(rip);
  127. }
  128.  
  129.  
  130. /*===========================================================================*
  131.  *                do_open                         *
  132.  *===========================================================================*/
  133. PUBLIC int do_open()
  134. {
  135. /* Perform the open(name, flags,...) system call. */
  136.  
  137.   int create_mode = 0;
  138.   int r;
  139.  
  140.   /* If O_CREAT is set, open has three parameters, otherwise two. */
  141.   if (mode & O_CREAT) {
  142.     create_mode = c_mode;    
  143.     r = fetch_name(c_name, name1_length, M1);
  144.   } else {
  145.     r = fetch_name(name, name_length, M3);
  146.   }
  147.  
  148.   if (r != OK) return(err_code); /* name was bad */
  149.   return common_open(mode, (mode_t) create_mode);
  150. }
  151.  
  152.  
  153. /*===========================================================================*
  154.  *                common_open                     *
  155.  *===========================================================================*/
  156. PRIVATE int common_open(oflags, omode)
  157. register int oflags;
  158. mode_t omode;
  159. {
  160. /* Common code from do_creat and do_open. */
  161.  
  162.   register struct inode *rip;
  163.   register int r;
  164.   register mode_t bits;
  165.   struct filp *fil_ptr;
  166.   dev_t dev;
  167.   int nonblocking, exist = TRUE;
  168.  
  169.   /* Remap the bottom two bits of oflags. */
  170.   bits = (mode_t) mode_map[oflags & O_ACCMODE];
  171.  
  172.   /* See if file descriptor and filp slots are available. */
  173.   if ( (r = get_fd(0, bits, &fd, &fil_ptr)) != OK) return(r);
  174.  
  175.   /* If O_CREATE is set, try to make the file. */ 
  176.   if (oflags & O_CREAT) {
  177.       /* Create a new inode by calling new_node(). */
  178.         omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
  179.         rip = new_node(user_path, omode, NO_ZONE, (off_t) 0);
  180.         r = err_code;
  181.         if (r == OK) exist = FALSE;      /* we just created the file */
  182.     else if (r != EEXIST) return(r); /* other error */
  183.     else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
  184.                         flag is set this is an error */
  185.   } else {
  186.      /* Scan path name. */
  187.         if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  188.   }
  189.  
  190.  
  191.   /* Only do the normal open code if we didn't just create the file. */
  192.   if (exist) {
  193.  
  194. #if 0    /* I doubt this, but what does POSIX say?
  195.      * I fixed the test anyway, to go with fixing the O_TRUNC test.
  196.      * BDE
  197.      */
  198.  
  199.       /* O_TRUNC and O_CREAT implies W_BIT */
  200.     if ((oflags & (O_TRUNC | O_CREAT)) == (O_CREAT | O_TRUNC))
  201.         bits |= W_BIT;
  202. #endif
  203.  
  204.       /* Check protections. */
  205.       if ((r = forbidden(rip, bits, 0)) == OK) {
  206.           /* Opening reg. files directories and special files differ. */
  207.           switch (rip->i_mode & I_TYPE) {
  208.                case I_REGULAR: 
  209.             /* Truncate regular file if O_TRUNC. */
  210.             if (oflags & O_TRUNC) {
  211.                 truncate(rip);
  212.                 wipe_inode(rip);
  213.             }
  214.             break;
  215.  
  216.                case I_DIRECTORY: 
  217.             /* Directories may be read but not written. */
  218.             r = (bits & W_BIT ? EISDIR : OK);
  219.             break;
  220.  
  221.                 case I_CHAR_SPECIAL:
  222.                 case I_BLOCK_SPECIAL:
  223.             /* Invoke the driver for special processing. */
  224.             dev = (dev_t) rip->i_zone[0];
  225.             nonblocking = oflags & O_NONBLOCK;
  226.             r = dev_open(rip, (int) bits, nonblocking);
  227.             break;
  228.  
  229.            case I_NAMED_PIPE:
  230.             r = pipe_open(rip, bits, oflags);
  231.             break;
  232.          }
  233.       }
  234.   }
  235.  
  236.   /* If error, release inode. */
  237.   if (r != OK) {
  238.     put_inode(rip);
  239.     return(r);
  240.   }
  241.   
  242.   /* Claim the file descriptor and filp slot and fill them in. */
  243.   fp->fp_filp[fd] = fil_ptr;
  244.   fil_ptr->filp_count = 1;
  245.   fil_ptr->filp_ino = rip;
  246.   fil_ptr->filp_flags = oflags;
  247.   return(fd);
  248. }
  249.  
  250. /*===========================================================================*
  251.  *                pipe_open                     *
  252.  *===========================================================================*/
  253. PRIVATE int pipe_open(rip, bits, oflags)
  254. register struct inode *rip;
  255. register mode_t bits;
  256. register int oflags;
  257. {
  258. /*  This function is called from do_creat and do_open, it checks if
  259.  *  there is at least one reader/writer pair for the pipe, if not
  260.  *  it suspends the caller, otherwise it revives all other blocked
  261.  *  pr